package knowledgebase.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import knowledgebase.model.AccessType;
import knowledgebase.model.Document;
import knowledgebase.model.DocumentBlock;
import knowledgebase.model.Role;
import knowledgebase.model.User;
import knowledgebase.service.Assembler;
import knowledgebase.service.DocumentBlockService;
import knowledgebase.service.DocumentService;
import knowledgebase.service.PermissionService;
import knowledgebase.service.UserService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author yzaretskyy
 */
@Controller
@RequestMapping("/article")
public class ArticleController {

    Log log = LogFactory.getLog(getClass());
    @Autowired
    private DocumentBlockService documentBlockService;
    @Autowired
    private DocumentService documentService;
    @Autowired
    private UserService userService;
    @Autowired
    private PermissionService permissionService;

    @RequestMapping(value = "/save_or_update_article", method = RequestMethod.POST)
    @ResponseBody
    public String updateArticle(@RequestParam(required = false) String docId, @RequestParam String articleTitle, @RequestParam String hierarchy, @RequestParam String[] docBlocksData, @RequestParam String[] docBlocksId) {
        boolean isCreante = docId == null || docId.equals("");
        docId = documentService.saveOrUpdateDocument(docId, articleTitle, hierarchy);
        documentBlockService.saveAllDocumentBlock(docBlocksData, docBlocksId, docId, hierarchy);
        //if (isCreante) {
            Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            String userName = (principal instanceof Assembler) ? ((Assembler) principal).getUsername() : "";
            User user = userService.findUserByName(userName);
            permissionService.setPermisiions(docBlocksId, true, true, true, new String[]{user.getId()+""}, new String[]{});
        //}
        return docId;
    }

    @RequestMapping(value = "/create", method = RequestMethod.GET)
    public ModelAndView showCreateArticle() {
        ModelAndView model = new ModelAndView("create_article");
        model.addObject("createArticle", true);
        return model;
    }

    @RequestMapping(value = "/edit/{articleId}", method = RequestMethod.GET)
    public ModelAndView showEditArticle(@PathVariable(value = "articleId") String articleId) {
        ModelAndView model = new ModelAndView("create_article");
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String userName = (principal instanceof Assembler) ? ((Assembler)principal).getUsername() : "";
        User user = userService.findUserByName(userName);
        boolean globalRolesPermissionForEdit = false;
        boolean globalRolesPermissionForCreate = false;
        boolean globalRolesPermissionForDelete = false;
        for(Role role : user.getRoles()) {
            if(globalRolesPermissionForCreate && globalRolesPermissionForDelete && globalRolesPermissionForEdit) {
                break;
            }
            List<AccessType> roleGlobalPermissions = permissionService.getGlobalRolePermissions(role);
            globalRolesPermissionForCreate = roleGlobalPermissions.contains(new AccessType(1, null));
            globalRolesPermissionForEdit = roleGlobalPermissions.contains(new AccessType(2, null));
            globalRolesPermissionForDelete = roleGlobalPermissions.contains(new AccessType(4, null));
        }
        Map<String,Object> articleElements = getArticleById(articleId, new AccessType(2, null));
        if(articleElements.size() == 1 && !globalRolesPermissionForCreate && !globalRolesPermissionForDelete && !globalRolesPermissionForEdit) {
            model.setViewName("forbidden");
        } else {
            model.addAllObjects(articleElements);
            model.addObject("canCreate", globalRolesPermissionForCreate);
            model.addObject("canEdit", globalRolesPermissionForEdit);
            model.addObject("canDelete", globalRolesPermissionForDelete);
        }
        return model;
    }

    @RequestMapping(value = "/user_articles")
    public ModelAndView showUserArticles() {
        ModelAndView model = new ModelAndView("user_articles");
        User user = userService.findUserByName(((Assembler) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
        model.addObject("articles", documentService.getDocumentsByOwner(user));
        return model;
    }

//    @RequestMapping(value = "/view/{articleId}")
//    public ModelAndView viewArticle(@PathVariable(value = "articleId") String articleId) {
//        ModelAndView model = new ModelAndView("view_article");
//        model.addAllObjects(getArticleById(articleId));
//        return model;
//    }
    @RequestMapping(value = "/view/{articleId}")
    public ModelAndView viewArticle(@PathVariable(value = "articleId") String articleId) {
        ModelAndView model = new ModelAndView("view_article");
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String userName = (principal instanceof Assembler) ? ((Assembler)principal).getUsername() : "";
        User user = userService.findUserByName(userName);
        boolean globalRolesPermissionForRead = false;
        for(Role role : user.getRoles()) {
            if(globalRolesPermissionForRead) {
                break;
            }
            List<AccessType> roleGlobalPermissions = permissionService.getGlobalRolePermissions(role);
            globalRolesPermissionForRead = roleGlobalPermissions.contains(new AccessType(3, null));
        }
        Map<String,Object> articleElements = getArticleById(articleId, new AccessType(3, null));
        if(articleElements.size() == 1 && !globalRolesPermissionForRead) {
            model.setViewName("forbidden");
        } else {
            model.addAllObjects(articleElements);
            model.addObject("canRead", globalRolesPermissionForRead);
        }
        //model.addAllObjects(getArticleById(articleId, new AccessType(3, null)));
        return model;
    }

    private Map<String, Object> getArticleById(String articleId, AccessType accessType) {
        Map<String, Object> map = new HashMap<String, Object>();
        Document doc = documentService.getDocumentById(articleId);
        map.put("article", doc);
        if (doc != null) {
            List<DocumentBlock> docBlocks = documentBlockService.getDocumentBlocksByDocumentId1(doc, accessType);
            map.put("docBlocks", docBlocks.isEmpty() ? null : docBlocks);
        }
        return map;
    }
}
